var visualHUD = {
	constructor: {},
	setupHudItem: { 
		'general': function(element, dataObject, updateObject){
			
			var props = dataObject.properties;
			
			var updateObject = updateObject || {};
			var oldSettings = $.extend({}, props);
			
			$.extend(props, updateObject);
			
			var iconBlock = dataObject.DOM.iconBlock;
			var icon = dataObject.DOM.icon;
			var textBlock = dataObject.DOM.textBlock;
			var counter = dataObject.DOM.counter;
			
			var isPowerup = props.name == 'powerupIndicator';
			var isTimer = props.name == 'timer';
			var isAmmo = props.name == 'ammoIndicator';
			
			var iconMargins = {
				'left': 'Right',
				'top': 'Bottom',
				'right': 'Left',
				'bottom': 'Top'
			};
			
			var iconPositionFn = props.iconPosition == 'left' || props.iconPosition == 'right' ? 'removeClass' : 'addClass';
			if(!isPowerup) {
				element[iconPositionFn]('icon-top');
			};
			
			var imargin = 'margin' + iconMargins[props.iconPosition];			
			var textbox = visualHUD.fontToBoxSize(props.textSize/100);

			if(isPowerup || isTimer){
				textbox[0] = '';
			};

			textBlock.width(textbox[0]).height(textbox[1]);
			
			if(updateObject.textSize != oldSettings.textSize) {
				counter.css({
					'line-height': textbox[1] + 'px',
					'font-size': props.textSize + '%'
				});
			};

			if(updateObject.iconSize != oldSettings.iconSize) {
				iconBlock.css({
					'width': props.iconSize + 'px',
					'height': props.iconSize + 'px'
				}).css({
					'display': props.iconSize * 1 == 0 ? 'none' : ''
				})
				
			};

			if(updateObject.textOpacity != oldSettings.textOpacity || updateObject.iconOpacity != oldSettings.iconOpacity){
				var iconOpacity = isPowerup ? 1 :  props.iconOpacity / 100;
				textBlock.css('opacity', props.textOpacity / 100);
				iconBlock.css('opacity', iconOpacity);
			};
			   
			var iconData = visualHUD.constructor.icons[props.name];

			if(updateObject.iconStyle != oldSettings.iconStyle){
				if(isPowerup){
					icon.each(function(i){
						this.src = iconData[i].url
					});
				} else {
					icon.attr('src', iconData[props.iconStyle].url);
				};
			};
			
			if(isPowerup){
				var lastChild = element.find('div.powerup-item:last').eq(0)
				lastChild.css('margin', 'auto');
				if(!props.singlePowerup){
					lastChild.css('margin-' + props.iconPosition, props.iconSpacing + 'px');
				}
				var miltiItemsCSS = props.singlePowerup ? 'addClass' : 'removeClass';
				element[miltiItemsCSS]('single-powerup');
			} else {
				iconBlock.css('margin', 'auto').css(imargin, props.iconSpacing + 'px');
			};

			
			if(updateObject.text != oldSettings.text){
				counter.text(props.text);
			};

			
			var ranges = visualHUD.constructor.colorRangeValues;
			var textValue = new Number(props.text);
			var color = props.textColor || '#FFFFFF';
			props.textColor = color.replace('#','');
			
			var range = 'high';
			var colorRangeObject = props.colorRanges;
			
			if(colorRangeObject){
				for(var a =0, b = colorRangeObject.length; a < b; a++){
					var range = colorRangeObject[a].range;
					
					if(textValue >= range[0] && textValue <= range[1]){
						props.textColor = colorRangeObject[a].color;
						break;
					}
				};
			};
			
/*			for(var k in ranges){
				if(textValue >= ranges[k][0] && textValue <= ranges[k][1]){
					color = props['colorRange_' + k];
					if(color) colorRangeObject = true;
					break;
				};
			};
*/			
			counter.css({
				'color': '#' + props.textColor,
			});

			
			if(updateObject.iconPosition != oldSettings.iconPosition){
				if(isPowerup) {
					element.removeClass('stack-' + oldSettings.iconPosition).addClass('stack-' + props.iconPosition);
					var verticalLayout =  props.iconPosition.match(/top|bottom/gi);
					if(verticalLayout){
						element.width(element.children().eq(0).width());
					} else {
						element.width('auto');
					};
				} else {
					if(props.iconPosition == 'left' || props.iconPosition == 'top'){
						var blocks = [iconBlock, textBlock];
					}else {
						var blocks = [textBlock, iconBlock];
					};
					
					for(var a = 0, b = blocks.length; a < b; a++){
						blocks[a].appendTo(element);
					};
				};
			};


			if(!dataObject.form){

				var form = visualHUD.formGenerator.createForm(visualHUD.application.settingsArea).css('visibility', 'hidden');
				visualHUD.formGenerator.createFormHeader(props, form);
				
				var formWrapper = form.append('<div class="app-form-container"></div>').find('div.app-form-container');
				
				var fieldset = visualHUD.formGenerator.createFieldset('Icon properties', formWrapper);
				var iStyleWrap = false;
				
				if(!isPowerup){
					if(iconData.length > 1) {
						var selectIconOptions = {};
	
/*	'armorIndicator': [
		{
			name: 'QL Armor',
			url: 'resources/images/icons/armor.png',

		},
		{
			name: 'Q3A Armor',
			armor: 'resources/images/icons/iconr_red.png'
		}
	],
	*/
						for(a = 0, b = iconData.length; a < b; a++){
							selectIconOptions[a] = iconData[a].name
						};
						
						iStyleWrap = visualHUD.formGenerator.createSelect({
							'name': 'iconStyle',
							'label': 'Icon',
							'width': '100px',
							'value': props.iconStyle,
							'options': selectIconOptions
						}, fieldset);
					};
	
					var iPositionWrap = visualHUD.formGenerator.createSelect({
						'name': 'iconPosition',
						'label': 'Position',
						'value': props.iconPosition,
						'width': iStyleWrap ? '60px' : '100px',
						'options': {
							'left': 'Left',
							'top': 'Top',
							'right': 'Right',
							'bottom': 'Bottom'
						}
					}, fieldset);
	
					if(iStyleWrap){
						iPositionWrap.find('select').insertAfter(iStyleWrap.find('select').addClass('mr-5'));
						iPositionWrap.remove();
					};
				} else {
					visualHUD.formGenerator.createSelect({
						'name': 'iconPosition',
						'label': 'Order',
						'value': props.iconPosition,
						'width': '120px',
						'options': {
							'left': 'Left to right',
							'right': 'Right to left',
							'top': 'Top to bottom',
							'bottom': 'Bottom to top'
						}
					}, fieldset);
				};
				
				visualHUD.formGenerator.createRangeInput({
					'name': 'iconSpacing',
					'label': 'Margin',
					'min': 0,
					'max': 32,
					'value': props.iconSpacing
				}, fieldset);
				
				visualHUD.formGenerator.createRangeInput({
					'name': 'iconSize',
					'label': 'Size',
					'min': 0,
					'max': 32,
					'value': props.iconSize
				}, fieldset);

				if(!isPowerup && !isAmmo){
					visualHUD.formGenerator.createRangeInput({
						'name': 'iconOpacity',
						'label': 'Opacity',
						'min': 0,
						'max': 100,
						'value': props.iconOpacity
					}, fieldset);
					
					visualHUD.formGenerator.createCheckbox({
						'name': 'teamColors',
						'label': 'Use team colors',
						'value': props.teamColors
					}, fieldset);
				};
				
				if(isPowerup){
					props.singlePowerup = false;
					visualHUD.formGenerator.createCheckbox({
						'name': 'singlePowerup',
						'label': 'Single icon',
						'value': props.singlePowerup
					}, fieldset);					
				};
				
				fieldset = visualHUD.formGenerator.createFieldset('Text properties', formWrapper);

				var textlength = 3;
				if(props.name == 'timer') textlength = 5;
				if(props.name == 'powerupIndicator') textlength = 2;

				if(!colorRangeObject){
					var picker = visualHUD.formGenerator.createColorPicker({
						'name': 'textColor',
						'label': 'Color',
						'size': 6,
						'maxlength': 6,
						'value': props.textColor,
					}, fieldset);
				};
				
				if(!isPowerup){
					var textLabel = visualHUD.formGenerator.createTextBox({
						'name': 'text',
						'label': 'Text',
						'maxlength': textlength,
						'size': 4,
						'value': props.text
					}, fieldset);
					
					if(!colorRangeObject)
						textLabel.addClass('counter-text');
				};
				
				visualHUD.formGenerator.createRangeInput({
					'name': 'textSize',
					'label': 'Size',
					'min': 0,
					'max': 100,
					'value': props.textSize
				}, fieldset);

				visualHUD.formGenerator.createRangeInput({
					'name': 'textOpacity',
					'label': 'Opacity',
					'min': 0,
					'max': 100,
					'value': props.textOpacity
				}, fieldset);

				if(colorRangeObject){
					fieldset = visualHUD.formGenerator.createFieldset('Color range', formWrapper);
					visualHUD.formGenerator.createColorRange(props.colorRanges, fieldset);
				};
			
				var buttonsWrapper = visualHUD.formGenerator.createFieldset('Actions', formWrapper);
				
				var alignItemsList = visualHUD.formGenerator.createAlignControl(buttonsWrapper);
//				visualHUD.formGenerator.createStyleButtons({element: element}, buttonsWrapper);
				

				
				var actionsPanel = visualHUD.formGenerator.createActionsPanel(null, form);
				
 				visualHUD.formGenerator.createToolbarButton({
					'name': 'delete',
					'label': 'Delete',
					'icon': 'trash',
					'fn': visualHUD.application.deleteElement,
					'args': null,
				}, actionsPanel);				
				
				dataObject.form = form.addClass('hidden').css('visibility', 'visible');
				
				visualHUD.formGenerator.linkForm(form, element);
			};
			
			element.css('visibility', 'visible').data('HUDItem', dataObject);

		},
		'obits': function(element, dataObject, updateObject){
			var props = dataObject.properties;
			
			var updateObject = updateObject || {};
			var oldSettings = $.extend({}, props);
			
			$.extend(props, updateObject);

			var iconData = visualHUD.constructor.icons[props.name];
			var icon = dataObject.DOM.icon;
			if(updateObject.iconStyle != oldSettings.iconStyle){
				icon.attr('src', iconData[props.iconStyle].url);
			};
			
			if(!dataObject.form){

				var form = visualHUD.formGenerator.createForm(visualHUD.application.settingsArea).css('visibility', 'hidden');
				visualHUD.formGenerator.createFormHeader(props, form);
				var formWrapper = $('<div class="app-form-container" />').appendTo(form);
				
				
				
				var buttonsWrapper = visualHUD.formGenerator.createFieldset('Actions', formWrapper);
				var alignItemsList = visualHUD.formGenerator.createAlignControl(buttonsWrapper);
				
				var actionsPanel = visualHUD.formGenerator.createActionsPanel(null, form);
				
 				visualHUD.formGenerator.createToolbarButton({
					'name': 'delete',
					'label': 'Delete',
					'icon': 'trash',
					'fn': visualHUD.application.deleteElement,
					'args': null,
				}, actionsPanel);	
				
				var actionsPanel = visualHUD.formGenerator.createActionsPanel(null, form);
				
 				visualHUD.formGenerator.createToolbarButton({
					'name': 'delete',
					'label': 'Delete',
					'icon': 'trash',
					'fn': visualHUD.application.deleteElement,
					'args': null,
				}, actionsPanel);	
				
				dataObject.form = form.css('visibility', 'visible').addClass('hidden');
			};
			
			element.css('visibility', 'visible').data('HUDItem', dataObject);
			
		},
		'iconItem': function(element, dataObject, updateObject){

			
			var props = dataObject.properties;
			
			var updateObject = updateObject || {};
			var oldSettings = $.extend({}, props);
			
			$.extend(props, updateObject);
			
			var iconBlock = dataObject.DOM.iconBlock;
			var icon = dataObject.DOM.icon;	
			
			if(updateObject.iconSize != oldSettings.iconSize || updateObject.iconOpacity != oldSettings.iconOpacity) {
				iconBlock.css({
					'width': props.iconSize + 'px',
					'height': props.iconSize + 'px',
					'opacity': props.iconOpacity / 100
				}).css({
					'display': props.iconSize * 1 == 0 ? 'none' : ''
				})
				
			};

			var iconData = visualHUD.constructor.icons[props.name];

			if(updateObject.iconStyle != oldSettings.iconStyle){
				icon.attr('src', iconData[props.iconStyle].url);
			};
			
			if(!dataObject.form){

				var form = visualHUD.formGenerator.createForm(visualHUD.application.settingsArea).css('visibility', 'hidden');
				visualHUD.formGenerator.createFormHeader(props, form);
				var formWrapper = $('<div class="app-form-container" />').appendTo(form);
				
				var fieldset = visualHUD.formGenerator.createFieldset('Icon properties', formWrapper);

				if(iconData.length > 1) {
					var selectIconOptions = {};

/*	'armorIndicator': [
	{
		name: 'QL Armor',
		url: 'resources/images/icons/armor.png',

	},
	{
		name: 'Q3A Armor',
		armor: 'resources/images/icons/iconr_red.png'
	}
],
*/
					for(a = 0, b = iconData.length; a < b; a++){
						selectIconOptions[a] = iconData[a].name
					};
					
					iStyleWrap = visualHUD.formGenerator.createSelect({
						'name': 'iconStyle',
						'label': 'Icon',
						'width': '100px',
						'value': props.iconStyle,
						'options': selectIconOptions
					}, fieldset);
				};
					
				visualHUD.formGenerator.createRangeInput({
					'name': 'iconSize',
					'label': 'Size',
					'min': 8,
					'max': 48,
					'value': props.iconSize
				}, fieldset);

				visualHUD.formGenerator.createRangeInput({
					'name': 'iconOpacity',
					'label': 'Opacity',
					'min': 0,
					'max': 100,
					'value': props.iconOpacity
				}, fieldset);
				
				var buttonsWrapper = visualHUD.formGenerator.createFieldset('Actions', formWrapper);
				
				var alignItemsList = visualHUD.formGenerator.createAlignControl(buttonsWrapper);
//				visualHUD.formGenerator.createStyleButtons({element: element}, buttonsWrapper);
				
				var actionsPanel = visualHUD.formGenerator.createActionsPanel(null, form);
				
 				visualHUD.formGenerator.createToolbarButton({
					'name': 'delete',
					'label': 'Delete',
					'icon': 'trash',
					'fn': visualHUD.application.deleteElement,
					'args': null,
				}, actionsPanel);	

//				var LI = $('#alignControls').children().clone().addClass('align-controls');
//				LI.prependTo(actionsPanel);
		
				dataObject.form = form.css('visibility', 'visible').addClass('hidden');
				
				visualHUD.formGenerator.linkForm(form, element);
			};
			
			element.css('visibility', 'visible').data('HUDItem', dataObject);
		},
		'flagIndicator': function(element, dataObject, updateObject){

			
			var props = dataObject.properties;
			
			var updateObject = updateObject || {};
			var oldSettings = $.extend({}, props);
			
			$.extend(props, updateObject);
			
			var iconBlock = dataObject.DOM.iconBlock;
			var icon = dataObject.DOM.icon;	

			var iconData = visualHUD.constructor.icons[props.name];

			if(updateObject.iconStyle != oldSettings.iconStyle){
				icon.attr('src', iconData[props.iconStyle].url);
			};
			
			if(updateObject.iconSize != oldSettings.iconSize || updateObject.iconOpacity != oldSettings.iconOpacity) {
				iconBlock.css({
					'width': props.iconSize + 'px',
					'height': props.iconSize + 'px',
					'opacity': props.iconOpacity / 100
				});
			};
			if(!dataObject.form){

				var form = visualHUD.formGenerator.createForm(visualHUD.application.settingsArea).css('visibility', 'hidden');
				visualHUD.formGenerator.createFormHeader(props, form);
				var formWrapper = $('<div class="app-form-container" />').appendTo(form);

				
				var buttonsWrapper = visualHUD.formGenerator.createFieldset('Actions', formWrapper);
				var alignItemsList = visualHUD.formGenerator.createAlignControl(buttonsWrapper);
				
				var actionsPanel = visualHUD.formGenerator.createActionsPanel(null, form);
				
 				visualHUD.formGenerator.createToolbarButton({
					'name': 'delete',
					'label': 'Delete',
					'icon': 'trash',
					'fn': visualHUD.application.deleteElement,
					'args': null,
				}, actionsPanel);	
				
				dataObject.form = form.css('visibility', 'visible').addClass('hidden');
			};
			element.css('visibility', 'visible').data('HUDItem', dataObject);
		},
		'scoreBox': function(element, dataObject, updateObject){

			
			var props = dataObject.properties;
			
			var updateObject = updateObject || {};
			var oldSettings = $.extend({}, props);
			
			$.extend(props, updateObject);
			
			var layout = props.layout;
			if(updateObject.layout != oldSettings.layout) {
				var layoutMap = {
					'vertical': 'scorebox-vertical',
					'horizontal': 'scorebox-horizontal'
				};
			
				for(var x in layoutMap){
					var fn = x == layout ? 'addClass' : 'removeClass';
					element[fn](layoutMap[x]);
				};
			};

			if(updateObject.spacing != oldSettings.spacing || updateObject.layout != oldSettings.layout) {
				var marginMap = {
					'vertical': 'Bottom',
					'horizontal': 'Right'
				};
				var boxElement = element.find('.item-icon').eq(0);
				boxElement.css('margin', 0).css('margin' + marginMap[props.layout], props.spacing + 'px');
			};
			
			if(updateObject.mode != oldSettings.mode) {
				var modeMap = {
					'ffa': 'ffa-score',
					'tdm': 'team-score'
				};
			
				for(var m in modeMap){
					var fn = m == props.mode ? 'addClass' : 'removeClass';
					element[fn](modeMap[m]);
				};
			};

			if(updateObject.scoreboxStyle != oldSettings.scoreboxStyle) {
				element.removeClass('style-' + oldSettings.scoreboxStyle).addClass('style-' + props.scoreboxStyle);
			};
			
			
			if(!dataObject.form){
				var form = visualHUD.formGenerator.createForm(visualHUD.application.settingsArea).css('visibility', 'hidden');
				visualHUD.formGenerator.createFormHeader(props, form);
				var formWrapper = $('<div class="app-form-container" />').appendTo(form);
				
				var fieldset = visualHUD.formGenerator.createFieldset('Scorebox properties', formWrapper);

				visualHUD.formGenerator.createSelect({
					'name': 'scoreboxStyle',
					'label': 'Style',
					'value': props.style,
					'width': '80%',
					'options': {
						'0': 'Classic',
						'1': 'Compact',
					}
				}, fieldset);
				
				visualHUD.formGenerator.createSelect({
					'name': 'layout',
					'label': 'Layout',
					'value': props.layout,
					'width': '80%',
					'options': {
						'vertical': 'Vertical',
						'horizontal': 'Horizontal',
					}
				}, fieldset);

				visualHUD.formGenerator.createRangeInput({
					'name': 'spacing',
					'label': 'Spacing',
					'min': 0,
					'max': 16,
					'value': props.spacing
				}, fieldset);
				
				visualHUD.formGenerator.createSelect({
					'name': 'mode',
					'label': 'Mode',
					'value': props.mode,
					'width': '80%',
					'options': {
						'ffa': 'FFA / Duel',
						'tdm': 'Teamplay',
					}
				}, fieldset);
				
				var buttonsWrapper = visualHUD.formGenerator.createFieldset('Actions', formWrapper);
				var alignItemsList = visualHUD.formGenerator.createAlignControl(buttonsWrapper);
				
				var actionsPanel = visualHUD.formGenerator.createActionsPanel(null, form);
				
 				visualHUD.formGenerator.createToolbarButton({
					'name': 'delete',
					'label': 'Delete',
					'icon': 'trash',
					'fn': visualHUD.application.deleteElement,
					'args': null,
				}, actionsPanel);
				
				dataObject.form = form.css('visibility', 'visible').addClass('hidden');
				
				visualHUD.formGenerator.linkForm(form, element);
			};
			
			element.css('visibility', 'visible').data('HUDItem', dataObject);
		}	,
		'rect': function(element, dataObject, updateObject){
			var props = dataObject.properties;
			
			var updateObject = updateObject || {};
			var oldSettings = $.extend({}, props);
			
			$.extend(props, updateObject);
			
			var $box = dataObject.DOM.box;
			var box = $box[0];
			
			if(updateObject.color != oldSettings.color) {
				box.style.backgroundColor = '#' + props.color;
			};
			if(updateObject.opacity != oldSettings.opacity) {
				$box.css('opacity', props.opacity / 100);
			};

			if(updateObject.width != oldSettings.width) {
				element[0].style.width = props.width + 'px';
			};
			
			if(updateObject.height != oldSettings.height) {
				element[0].style.height = props.height + 'px';
			};
			
			if(!dataObject.form){
				var form = visualHUD.formGenerator.createForm(visualHUD.application.settingsArea).css('visibility', 'hidden');
				visualHUD.formGenerator.createFormHeader(props, form);
				var formWrapper = $('<div class="app-form-container" />').appendTo(form);
				
				var fieldset = visualHUD.formGenerator.createFieldset('Area properties', formWrapper);

				visualHUD.formGenerator.createRangeInput({
					'name': 'width',
					'label': 'Width',
					'min': 10,
					'max': 640,
					'value': props.width
				}, fieldset)

				visualHUD.formGenerator.createRangeInput({
					'name': 'height',
					'label': 'Height',
					'min': 10,
					'max': 480,
					'value': props.height
				}, fieldset)
				
				visualHUD.formGenerator.createColorPicker({
					'name': 'color',
					'label': 'Fill color',
					'size': 6,
					'maxlength': 6,
					'value': props.color,
				}, fieldset);

				visualHUD.formGenerator.createRangeInput({
					'name': 'opacity',
					'label': 'Opacity',
					'min': 0,
					'max': 100,
					'value': props.opacity
				}, fieldset);
				
				
				var buttonsWrapper = visualHUD.formGenerator.createFieldset('Actions', formWrapper);
				var alignItemsList = visualHUD.formGenerator.createAlignControl(buttonsWrapper);
				var arrangeItemsList = visualHUD.formGenerator.createArrangeControl(buttonsWrapper);				
				
				var actionsPanel = visualHUD.formGenerator.createActionsPanel(null, form);


				
 				visualHUD.formGenerator.createToolbarButton({
					'name': 'delete',
					'label': 'Delete',
					'icon': 'trash',
					'fn': visualHUD.application.deleteElement,
					'args': null,
				}, actionsPanel);
				

				
				dataObject.form = form.css('visibility', 'visible').addClass('hidden');
				
				visualHUD.formGenerator.linkForm(form, element);
			};
			element.data('HUDItem', dataObject);
		}
	},
	
	updateControls: function(element, data){
		var form;
		for(var a in data){
			$(data).data(a, data[a]);
		};		
	},
	
	fontToBoxSize: function(size){
		return [Math.floor(104 * size), Math.floor(35 * size)];
	},
	hexToQLColor: function(_hex){
		var color = $.color(_hex);
		var qlColor = [];
		for(var a = 0, b = color.rgb.length; a < b; a++){
			qlColor[a] = color.rgb[a] / 255;
			qlColor[a] = Math.floor(qlColor[a] * 100);
			qlColor[a] = qlColor[a] / 100;
		};
		return qlColor.join(' ');
	},
	convertQLColor: function(_color){
		_color = _color.split(' ');
		var rgbColor = [];
		for(var a = 0, b = _color.length; a < b; a++){
			rgbColor[a] = Math.floor(_color[a] * 255);
		};
		var color = $.color(rgbColor);
		return color;
	},
	setupToolbar: function(_toolbarUL){
		var LI = _toolbarUL.children();

		var _this = this;
		var subMenuActive = 0;
		
		var setupMenu = function(_item){
			_item.click(function(event){
			 	event.preventDefault();
				
				var activeItems = LI.filter('.active').not(_item).removeClass('active');
				_item.toggleClass('active');
				var _active = _item.hasClass('active');

				if(_active && activeItems.length == 0){
					window.setTimeout(function(){
						$('body').bind('click.hideMenu', hideMenu);
					}, 20);
				} else {
					event.stopPropagation(); // this will prevent body click.hideMenu event
				};
			});
		};

		var setupSubMenu = function(_item){
			_item.click(function(event){
				hideMenu();
				event.stopPropagation();
			});
			_item.bind('mouseover', function(event){
				event.stopPropagation();
			});			
		};
		
		var hideMenu = function(){
			LI.filter('.active').removeClass('active');
			$('body').unbind('click.hideMenu');
		};
		
		LI.each(function(){
			var $this = $(this);
			var submenu = $this.find('ul');
			
			setupMenu($this);
			setupSubMenu(submenu);
		});
	}
};


visualHUD.formGenerator = {
	createForm: function(_wrapper){
		var form = $('<form class="app-form" />').delegate('input,select,button','focus', function(event){
			form.data('focusedElement', this);
		}).bind('click', function(event){			
			event.stopPropagation();
			if(event.type == 'click'){
				var $target = $(event.target);
				if($target.is('legend')){
					$target.parent().toggleClass('collapsed');
					return false;
				};
			};

		}).appendTo(_wrapper);
		
		form.submit(function(){
			return false;
		});
		
		return form;
	},
	createFormHeader: function(_data, _form){
		_form.append('<div class="control-header"><div class="header-wrap '+ _data.cssClass +'"><span class="item-type">Item:</span><div class="item-name">'+ _data.label +'</div></div></div>');
		return _form;
	},
	linkForm: function(_form, _element){
		_form.bind('change', function(event){
			var _data = _element.data('HUDItem');
			var name = event.target.name;
			var value = event.target.value;
			var isCheckbox = event.target.type == 'checkbox';
			
			var updateObject = $.extend({}, _data.properties);

			var colorRange = name.match(/colorRange_/);
			if(colorRange){
				var colorRangeIndex = new Number(name.replace(colorRange, ''));
				var currentRange = updateObject.colorRanges[colorRangeIndex];
				currentRange.color = value;
			};
			
			if(typeof _data.properties[name] != 'undefined' || colorRange){
				if(!colorRange) {
					updateObject[name] = isCheckbox ? event.target.checked : value;
				};
				
				visualHUD.setupHudItem[_data.properties.itemType](_element, _data, updateObject);
				visualHUD.application.getItemStatus(_element,_data);
			};
			
			
			
		});
		
	},
	createFieldset: function(_name, _form){
		var fieldset = $('<fieldset></fieldset>');
		if(_name){
			fieldset.append('<legend>'+ _name +'</legend>');
		};
		fieldset.appendTo(_form);
		
		return fieldset;
	},
	createActionsPanel: function(_name, _form){
		var fieldset = $('<fieldset class="form-actions"><ul class="app-toolbar"></ul></fieldset>');
		if(_name){
			fieldset.append('<legend>'+ _name +'</legend>');
		};
		fieldset.appendTo(_form);
		
		return fieldset.find('ul.app-toolbar');
	},
	createTextBox: function(_data, _form){
		var template = '<span class="f-label">{0}</span><span class="f-inputs">\
							<input type="text" size="{3}" name="{1}" value="{2}" maxlength="{4}"  />\
						</span>';
					
		var wrap = $('<label class="f-row" />');
		wrap.html(template.format(_data.label, _data.name, _data.value || '', _data.size || 32, _data.maxlength || '')).appendTo(_form);
		return wrap;
	},
	createRangeInput: function(_data, _form){
		var template = '<span class="f-label">{0}</span><span class="f-inputs">\
							<input type="text" size="8" maxlength="3" name="{1}" value="{2}"  />\
						</span>';
						
		var wrap = $('<div class="f-row" />');
		wrap.html(template.format(_data.label, _data.name, _data.value || '')).appendTo(_form);
		
		var input = wrap.find('input[type=text]');
		input.rangeinput({
			min: _data.min,
			max: _data.max,
			value: _data.value,
			precision: false,
			keyboard: false,
			progress: true
		}).focus(function(){ });

		return wrap;
	},
	createCheckbox: function(_data, _form){
		var template = '<div class="f-inputs f-checkboxes">\
							<label class="check-label"><input type="checkbox" name={0} {1}><span class="label">{2}</span></label>\
						</div>';
					
		var wrap = $('<div class="f-row" />');
		wrap.html(template.format(_data.name, _data.value ? 'checked="checked"' : '', _data.label)).appendTo(_form);
		return wrap;		
	},
	createRadioButtons: function(_data, _form){
	},
	createSelect: function(_data, _form){
		var template = '<span class="f-label">{0}</span><span class="f-inputs">\
							<select name="{1}"></select>\
						</span>';

		var wrap = $('<div class="f-row" />');
		wrap.html(template.format(_data.label, _data.name)).appendTo(_form);

		var selectElement = wrap.find('select').get(0);
		selectElement.style.width = _data.width || 'auto';
		for(var a in _data.options){
			var index = selectElement.options.length
			selectElement.options[index] = new Option(_data.options[a], a);
			if(_data.value == a){
				selectElement.selectedIndex = index;
			};
		};
		return wrap;
	},
	createButton: function(_data, _form){
		var template = '<button  name="{0}" value="{1}" class="{2}" title="{3}"><span class="{4}">{5}</span></button>';
		var icon =  _data.icon ? 'w-icon ' +  _data.icon : '';
		var wrap = $(template.format(_data.name, _data.label, _data.cssClass || '', _data.tooltip || '', icon, _data.label)).appendTo(_form);
		
		wrap.click(function(){
			return _data.fn.apply(visualHUD.application, _data.args || []);
		});
		
		return wrap;
	},
	createToolbarButton: function(_data, _form){
		var template = '<li class="{0}"><span class="item-name">{1}</span><strong class="item-value hidden"></strong></li>';
		var icon =  _data.icon || '';
		var wrap = $(template.format(_data.icon, _data.label)).appendTo(_form);
		
		wrap.click(function(){
			return _data.fn.apply(visualHUD.application, _data.args || []);
		});
		
		return wrap;
	},
	createAlignControl: function(_form){
		var template = '<span class="f-label">Align</span><span class="f-inputs"></span>';
		var wrap = $('<div class="f-row" />').html(template).appendTo(_form);
		$('#alignControls').clone(true).addClass('').appendTo(wrap.find('.f-inputs'));
		return wrap;
	},
	createArrangeControl: function(_form){
		var template = '<span class="f-label">Arrange</span><span class="f-inputs"></span>';
		var wrap = $('<div class="f-row" />').html(template).appendTo(_form);		
		$('#arrangeControls').clone(true).removeClass('hidden').appendTo(wrap.find('.f-inputs'));
		return wrap;
	},
	createStyleButtons: function(_data, _form){
		var template = '<span class="f-label">Style</span><span class="f-inputs"></span>';
		var wrap = $('<div class="f-row" />').html(template).appendTo(_form);
		var buttonsWrap = wrap.find('.f-inputs');
		this.createButton({
			'name': 'copy_style',
			'label': 'Copy',
			'cssClass': 'button-small mr-5',
			'icon': '',
			'fn': visualHUD.application.copyProperties,
			'args': [_data.element]
		}, buttonsWrap);

		var applyStyleButton = this.createButton({
			'name': 'apply_style',
			'label': 'Apply',
			'cssClass': 'button-small mr-5',
			'icon': '',
			'fn': visualHUD.application.applyProperties,
			'args': [_data.element]
		}, buttonsWrap);
		
		visualHUD.application.styleButtons.push(applyStyleButton.attr('disabled', !visualHUD.application.elementPropsClipboard).get(0));
	},
	createColorPicker: function(_data, _form){
		this.setupColorPicker();
		
		var wrap = this.createTextBox(_data, _form);		
		var input = wrap.find('input[type=text]');
		
		var colorPickerDIV = $('<div class="color-picker-box" />')
			.css('backgroundColor', '#' + _data.value)
			.insertAfter(input).click(function(event){
				visualHUD.formGenerator.colorpicker.colorInput = input;
				visualHUD.formGenerator.colorpicker.show($(this), event);
				return false;
			});
		if(_data.hint) {
			colorPickerDIV.clone().attr('class', 'color-picker-hint').css('backgroundColor', '').insertAfter(colorPickerDIV).html(_data.hint);
		}
		return wrap;
	},
	setupColorPicker: function(){
		this.colorpicker = this.colorpicker || new xpk.DHTMLArea(visualHUD.application.settingsArea,{
			delegate: true,
			fromSelector: 'div.color-picker-box',
			className: 'color-picker-wrapper clearfloat',
			init: function(){
				var _this = this;
				this.palette = visualHUD.constructor.colorPresets;
				
				for(var a = 0, b = this.palette.length; a<b; a++){
					this.palette[a] = this.palette[a].toUpperCase();
					this.menu.append('<div class="color-cell" style="background-color:'+ "#"+this.palette[a] +'"></div>');
				};
				
				this.paletteElements = this.menu.find('div.color-cell');
				var preventMouseleave = false;
				
				this.menu.bind('mouseover mouseout click', function(event){
					if(_this.activeElement) {
						var $target = $(event.target);
						var $colorCell = $target.closest('div.color-cell');
						
						if($colorCell.length) {
							var color = $colorCell.css('backgroundColor');
							var initialColor = $.color(color);
							
							var classFoo = event.type == 'mouseout' || event.type == 'click' ? 'removeClass' : 'addClass';
							
							if (event.type == 'mouseover') {
								_this.$activeElement.css('backgroundColor', color);
								color = $.color(color);
								_this.colorInput.val(color.hex.replace('#',''));
							} else if(event.type == 'mouseout'){
								if(!preventMouseleave) {
									_this.colorInput.val(_this.backgroundColor.hex.replace('#',''));
									_this.$activeElement.css('backgroundColor', _this.backgroundColor.hex);
								};
							}
							
							$colorCell[classFoo]('color-cell-hover');
							
							if(event.type == 'click') {
								preventMouseleave = true;
								_this.colorInput.trigger('change');
								_this.hide();
								return false;
							};
							preventMouseleave = false;
						};				
					};
				});
				
			},
			onshow: function(){
				this.backgroundColor = $.color(this.$activeElement.css('backgroundColor'));
				var currentIndex = $.inArray(this.backgroundColor.hex.replace('#','').toUpperCase(), this.palette);
				this.currentColorCell = this.paletteElements.eq(currentIndex).addClass('active-color');
			},
			onhide: function(){
//				var colorMatch = this.colorInput.val() == this.backgroundColor.hex.replace('#','');
//				console.log(colorMatch);
				this.currentColorCell.removeClass('active-color');
			}
		})		
	},
	createColorRange: function(_ranges, _form){
		var colors = visualHUD.constructor.colorRangeColors;
		var ranges = visualHUD.constructor.colorRangeValues;

		for(var a = 0, b = _ranges.length; a < b; a++){
			var range = _ranges[a];

			visualHUD.formGenerator.createColorPicker({
				'name': 'colorRange_' + a,
				'label': range.name,
				'size': 6,
				'maxlength': 6,
				'value': range.color,
				'hint': range.range.join(' - ')
			}, _form);	
		};
				
/*		for(var k in ranges){
			visualHUD.formGenerator.createColorPicker({
				'name': 'colorRange_' + k,
				'label': k,
				'size': 6,
				'maxlength': 6,
				'value': colors[k],
			}, _form);			
		}*/

	}
};

visualHUD.

visualHUD.constructor = {
	colorRangeValues: {
		'Low': [-999, 25],
		'Normal': [26,100],
		'High': [101, 999]
	},
	ammoColorRangeValues:{
		'Low': [-999, 5],
		'Normal': [6,100],
		'High': [101, 999]
	},	
	colorRangeColors:{
		'Low': 'FF0000',
		'Normal': 'FFFFFF',
		'High': 'FFFFFF'
	},
	
	colorPresets: [
		"FFFFFF","FF8AD8","FF928A","FFBA8A","fccc30","FDFF8A","DAFF58","a1fb6e","7ff7e0","54cdf5","5ba8f5","5537ff","a053ed",
		"CCCCCC","FF00BA","FF0000","F06300","FFA000","ECF000","BBF000","56F000","00F0C1","00B4F0","0077F0","2e15f1","732fbe",
		"999999","CC0087","CC0E00","CC5400","CC7F00","C9CC00","9FCC00","4ACC00","00CCA4","0099CC","0065CC","1a05c4","501a8c",
		"666666","990066","990A00","993F00","996000","979900","789900","389900","00997B","007399","004C99","1100a0","391166",
		"333333","660043","660700","662A00","664000","646600","506600","256600","006652","004C66","003266","0c0073","250b41",
		"000000","330021","330400","331500","332000","323300","273300","123300","003329","002633","001933","060033","190033"
	],
	fn: {
		createPowerupTemplate: function(template){
			template = template.replace(/hud-item/g, 'powerup-item');
			var wrapper = '<div class="hud-item"><div class="powerups-wrapper">{0}</div>';
			template = wrapper.format(template + template);
			return template;
		},
		checkExtendedData: function(currentData, dataTemplate){
			var count = 0;
			var matches = 0;
			for(var k in dataTemplate){
				count++;
				if(k in currentData) matches++;
			};
			return count == matches;
		},
		createGeneralItem: function(_data, _pos){
			var dataObject = {
				properties: $.extend({}, _data)
			};
			delete dataObject.properties.fn
			
			var colorRangeObject = _data.name.match(/armorIndicator|healthIndicator|ammoIndicator/gi);
			var ammoIndicator = _data.name.match(/ammoIndicator/gi);
			
			if(colorRangeObject && !_data.colorRanges){
				var colors = visualHUD.constructor.colorRangeColors;
				var ranges = ammoIndicator ? visualHUD.constructor.ammoColorRangeValues : visualHUD.constructor.colorRangeValues;
				dataObject.properties.colorRanges = [];
				for(var k in ranges){
					dataObject.properties.colorRanges.push({name: k, range: ranges[k], color: colors[k]});
				};
			}
			

			var props = dataObject.properties;
			var defaultItemData = visualHUD.constructor.itemData[_data.itemType];

			if(this.checkExtendedData(props, defaultItemData)) {
				var isPreset = true;
				defaultItemData = {};
			};
			
			$.extend(props, defaultItemData);
			
			var textbox = visualHUD.fontToBoxSize(props.textSize/100);
			var offset = visualHUD.application.hudElementsWrap.offset();
			
			var iconData = visualHUD.constructor.icons[_data.name];
			var iconURL = iconData[props.iconStyle].url;
			
			props.text = props.text || visualHUD.constructor.textLabels[_data.name];
			var counterText = props.text;
			
			var htmlTemplate = visualHUD.constructor.itemHTML[_data.itemType].format(iconURL, counterText);
			
			if(_data.name == 'powerupIndicator'){
				htmlTemplate = this.createPowerupTemplate(htmlTemplate);
				var defaultPowerupData = {
					 layout: 'vertical',
					 iconSize: 24,
					 textSize: 55,
					 iconSpacing: 4
				};
				if(this.checkExtendedData(props, defaultPowerupData)){
					defaultPowerupData = {};
				};
				$.extend(props, defaultPowerupData);
			};
			
			var element = $(htmlTemplate).css('visibility', 'hidden').appendTo(visualHUD.application.hudElementsWrap);
			
			var iconBlock = element.find('div.item-icon');
			var icon = iconBlock.find('img');//.attr('src', iconURL);
			
			//$.extend(props, {icon: iconData});
			
			var textBlock = element.find('div.item-counter');
			var counter = textBlock.find('span.counter');

			dataObject.DOM = {
				iconBlock: iconBlock,
				icon: icon,
				textBlock: textBlock,
				counter: counter
			};
			
			if(_pos){
				this.setElementPosition(element, _pos);
			} else {
				element.css({
					top: _data.coordinates.top,
					left: _data.coordinates.left
				})
			}

			visualHUD.setupHudItem[_data.itemType](element, dataObject);
			
			return element;
		},

		createIconItem: function(_data, _pos){

			var dataObject = {
				properties: $.extend({}, _data)
			};
			
			delete dataObject.properties.fn
			
			var props = dataObject.properties;
			var defaultItemData = visualHUD.constructor.itemData[_data.itemType];

			if(this.checkExtendedData(props, defaultItemData)) {
				var isPreset = true;
				defaultItemData = {};
			};
			
			$.extend(props, defaultItemData);
			

			var offset = visualHUD.application.hudElementsWrap.offset();
			var htmlTemplate = visualHUD.constructor.itemHTML[_data.itemType].format('');
			
			var element = $(htmlTemplate).css('visibility', 'hidden').appendTo(visualHUD.application.hudElementsWrap);
			var iconBlock = element.find('div.item-icon');
			var icon = iconBlock.find('img');
			
			dataObject.DOM = {
				iconBlock: iconBlock,
				icon: icon
			};
		
			visualHUD.setupHudItem[_data.itemType](element, dataObject);
			
			if(_pos){
				this.setElementPosition(element, _pos);
			} else {
				element.css({
					top: _data.coordinates.top,
					left: _data.coordinates.left
				})
			}
			
			return element;
		},
		
		createScorebox: function(_data, _pos){
			var dataObject = {
				properties: $.extend({}, _data)
			};
			
			delete dataObject.properties.fn			
			var props = dataObject.properties;
			var defaultItemData = visualHUD.constructor.itemData[_data.itemType];
			if(this.checkExtendedData(props, defaultItemData)) {
				var isPreset = true;
				defaultItemData = {};
			};
			
			$.extend(props, defaultItemData);
		
			var htmlTemplate = visualHUD.constructor.itemHTML[_data.itemType];
			var element = $(htmlTemplate).css('visibility', 'hidden').appendTo(visualHUD.application.hudElementsWrap);
			dataObject.DOM = {};
			
			if(_pos){
				this.setElementPosition(element, _pos);
			} else {
				element.css({
					top: _data.coordinates.top,
					left: _data.coordinates.left
				})
			}		
			
			visualHUD.setupHudItem[_data.itemType](element, dataObject);
			return element;			
		},
		createTimer: function(_data, _pos){
			return this.createGeneralItem(_data, _pos);
		},
		createArmorIndicator: function(_data, _pos){
			return this.createGeneralItem(_data, _pos);
		},
		createAmmoIndicator: function(_data, _pos){
			return this.createGeneralItem(_data, _pos);
		},
		createHealthIndicator: function(_data, _pos){
			return this.createGeneralItem(_data, _pos);
		},
		createPowerupIndicator: function(_data, _pos){
			return this.createGeneralItem(_data, _pos);
		},
		
		createCTFPowerupIndicator: function(_data, _pos){
			return this.createIconItem(_data, _pos);
		},
		
		createPlayerItem: function(_data, _pos){
			return this.createIconItem(_data, _pos);
		},
		
		createObits: function(_data, _pos){
			var dataObject = {
				properties: $.extend({}, _data),
				DOM: {}
			};
			
			delete dataObject.properties.fn
			
			var props = dataObject.properties;
			var defaultItemData = visualHUD.constructor.itemData[_data.itemType];
			if(this.checkExtendedData(props, defaultItemData)) {
				var isPreset = true;
				defaultItemData = {};
			};
			
			$.extend(props, defaultItemData);

			var counterText = visualHUD.constructor.textLabels[_data.name];
			var htmlTemplate = visualHUD.constructor.itemHTML[_data.itemType].format(counterText[0], props.iconURL, counterText[1]);
			
			var element = $(htmlTemplate).css('visibility', 'hidden').appendTo(visualHUD.application.hudElementsWrap);
			dataObject.DOM.icon = element.find('img');
		
			
			if(_pos){
				this.setElementPosition(element, _pos);
			} else {
				element.css({
					top: _data.coordinates.top,
					left: _data.coordinates.left
				})
			};
			
			visualHUD.setupHudItem[_data.itemType](element, dataObject);
			
			
			return element;
		},
		createFlagIndicator: function(_data, _pos){
			return this.createIconItem(_data, _pos)
		},
		createRect: function(_data, _element){
			if(!_element){
				var _element = visualHUD.application.drag.drawBox.clone().prependTo(visualHUD.application.hudElementsWrap);
			};
			
			var dataObject = {
				properties: $.extend({}, _data),
				DOM: {
					box: _element.find('.hud-item-box')
				}
			};

			var props = dataObject.properties;
			var defaultItemData = visualHUD.constructor.itemData[_data.itemType];
			if(this.checkExtendedData(props, defaultItemData)) {
				var isPreset = true;
				defaultItemData = {};
			};
			
			$.extend(props, defaultItemData);
			
			props.width = props.width || _element.width();
			props.height = props.height || _element.height();
			
			visualHUD.setupHudItem[_data.itemType](_element, dataObject);
				
			if( _data.coordinates){
				_element.css({
					top: _data.coordinates.top,
					left: _data.coordinates.left
				});				
			};
			
			return _element;
		},
		setElementPosition: function(element, _pos){
			var offset = visualHUD.application.hudElementsWrap.offset();
			element.css({
				top: Math.round(_pos.y - offset.top - element.height()/2),
				left:  Math.round(_pos.x - offset.left - element.width()/2),
			});
		}
	},
	itemData: {
		'general': {
			iconPosition: 'left',
			iconSpacing: 10,
			iconOpacity: 100,
			iconSize: 32,
			iconStyle: 0,
			textSize: 100,
			textOpacity: 100,
			textStyle: 3,
			teamColors: true
		},
		'iconItem': {
			iconStyle: 0,
			iconSize: 16,
			iconOpacity: 100
		},
		'scoreBox': {
			scoreboxStyle: 0,
			layout: 'horizontal',
			mode: 'ffa',
			spacing: 1,
			iconSpacing: 10//  horisontal || vertical
		},
		'flagIndicator':{
			iconStyle: 0,
			iconSize: 32,
			iconOpacity: 100
		},
		'obits': {
			iconStyle: 0
		},
		'rect':{
			color: 'FFFFFF',
			opacity: 100,
			width: 0,
			height: 0
		}
	},
	itemHTML: {
		'general': '<div class="hud-item">\
						<div class="item-icon" style="width: 32px; height: 32px;"><img src="{0}" /></div>\
						<div class="item-counter"><span class="counter">{1}</span></div>\
					</div>',
		'obits': '<div class="hud-item obit-item">\
					<div class="item-counter"><span class="counter">{0}</span></div>\
					<div class="item-icon"><img src="{1}" /></div>\
					<div class="item-counter"><span class="counter">{2}</span></div>\
				</div>',
		'iconItem': '<div class="hud-item icon-item">\
							<div class="item-icon"><img src="{0}" /></div>\
						</div>',
		'scoreBox': '<div class="hud-item scorebox-item team-score">\
							<div class="item-icon team-red"></div><div class="item-icon team-blue"></div>\
						</div>',
		'flagIndicator': '<div class="hud-item icon-item">\
							<div class="item-icon"><img src="{0}" /></div>\
						</div>'
	},
	icons: {
		'armorIndicator': [
			{
				name: 'QL Armor',
				url: 'resources/images/icons/armor.png',
	
			},
			{
				name: 'Q3A Armor',
				url: 'resources/images/icons/iconr_red.png'
			}
		],
		'healthIndicator': [
			{
				name: 'QL Health',
				url: 'resources/images/icons/health.png',
	
			},
			{
				name: 'Head icon',
				url: 'resources/images/icons/icon_head.png'
			}
		],		
		'ammoIndicator': [
			{
				name: 'Rocketlauncher',
				url: 'resources/images/icons/iconw_rocket.png'
			}
		],
		'powerupIndicator': [
			{
				name: 'Quad',
				url:'resources/images/icons/quad.png'
			},
			{
				name: 'Regeneration',
				url:'resources/images/icons/regen.png'
			}		
		],
		'CTFPowerupIndicator': [
			{
				name: 'Scout',
				url:'resources/images/icons/scout.png'
			}
		],		
		'scoreBox': [],
		'timer': [
			{
				name: 'Clock',
				url:'resources/images/icons/icon_time.png'
			}
		],		
		'playerItem': [
			{
				name: 'Medkit',
				url:'resources/images/icons/medkit.png'
			}
		],
		'obits': [
			{
				name: 'Rocketlauncher',
				url: 'resources/images/icons/iconw_rocket.png'
			}			  
		],
		'flagIndicator': [
			{
				name: 'Flag 1',
				url:'resources/images/icons/flag.png'
			},
			{
				name: 'Flag 2',
				url:'resources/images/icons/iconf_blu1.png'
			}
			
		]
	},
	textLabels: {
		'armorIndicator': '100',
		'healthIndicator': '200',		
		'ammoIndicator': '200',
		'powerupIndicator': '32',
		'CTFPowerupIndicator': '',		
		'scoreBox': '',
		'timer': '2:18',		
		'playerItem': '',
		'obits': ['Klesk', 'Xaero'],
		'flagIndicator': ''
	}
};

visualHUD.constructor.buttons = {
	'healthIndicator': {
		'itemType': 'general',
		'cssClass': 'lib-element-health',
		'label': 'Health indicator',
		'fn': visualHUD.constructor.fn.createHealthIndicator
	},		
	'armorIndicator': {
		'itemType': 'general',
		'cssClass': 'lib-element-armor',
		'label': 'Armor indicator',
		'fn': visualHUD.constructor.fn.createArmorIndicator
	},
	'ammoIndicator': {
		'itemType': 'general',
		'cssClass': 'lib-element-ammo',
		'label': 'Ammo indicator',
		'fn': visualHUD.constructor.fn.createAmmoIndicator
	},
	'timer': {
		'itemType': 'general',
		'cssClass': 'lib-element-timer',
		'label': 'Timer',
		'fn': visualHUD.constructor.fn.createTimer
	},	
	'powerupIndicator': {
		'itemType': 'general',
		'cssClass': 'lib-element-powerup',
		'label': 'Powerup timer',
		'fn': visualHUD.constructor.fn.createPowerupIndicator
	},
	'scoreBox': {
		'itemType': 'scoreBox',
		'cssClass': 'lib-element-scorebox',
		'label': 'Scorebox',
		'fn': visualHUD.constructor.fn.createScorebox
	},
	'playerItem': {
		'itemType': 'iconItem',
		'cssClass': 'lib-element-player-item',
		'label': 'Usable item indicator',
		'fn': visualHUD.constructor.fn.createPlayerItem
	},
	'CTFPowerupIndicator': {
		'itemType': 'iconItem',
		'cssClass': 'lib-element-ctf-powerup',
		'label': 'CTF powerup indicator',
		'fn': visualHUD.constructor.fn.createCTFPowerupIndicator
	},

	'obits': {
		'itemType': 'obits',
		'cssClass': 'lib-element-obit',
		'label': 'Graphical obits',
		'fn': visualHUD.constructor.fn.createObits
	},
	'flagIndicator': {
		'itemType': 'iconItem',
		'cssClass': 'lib-element-flag',
		'label': 'Flag indicator',
		'fn': visualHUD.constructor.fn.createFlagIndicator
	},
	'rectangleBox': {
		'name': 'rectangleBox',
		'itemType': 'rect',
		'label': 'Rectangle box',
		'cssClass': 'lib-element-rect hidden',	
		'fn': visualHUD.constructor.fn.createRect
	}
};

visualHUD.dragInterface = {
	offsets: [],
	setMode: function(mode){
		this.mode = mode;
		return this;
	},
	setDragHandle: function(resizeHandle){
		this.resizeHandle = resizeHandle;
		return this;
	},
	startDrawRect: function(event, element){
		this.currentElement = this.drawBox.clone().css({top: this.mouse.y, left: this.mouse.x}).prependTo(visualHUD.application.hudElementsWrap);
		this.mode = 'drawRect';
	},
	drawRect: function(event, position, mouse){
		if(this.options.grid) {
			this.mouse.x -= this.mouse.x % this.options.grid;
			this.mouse.y -= this.mouse.y % this.options.grid;					
			mouse.x -= mouse.x % this.options.grid;
			mouse.y -= mouse.y % this.options.grid;						
		};
		
		var w = Math.abs(this.mouse.x - mouse.x);
		var h = Math.abs(this.mouse.y - mouse.y);
		
		var t = Math.min(this.mouse.y, mouse.y) - visualHUD.application.canvasPosition.top;
		var l = Math.min(this.mouse.x, mouse.x) - visualHUD.application.canvasPosition.left;
		
		if(t < 0){
			t = 0;
			h = this.mouse.y - visualHUD.application.canvasPosition.top;
		} else {
			h = mouse.y > visualHUD.application.canvasPosition.bottom ?visualHUD.application.canvasPosition.bottom - this.mouse.y : h;
		};
		
		if(l < 0){
			l = 0;
			w =this.mouse.x - visualHUD.application.canvasPosition.left;
		} else {
			w = mouse.x > visualHUD.application.canvasPosition.right ?visualHUD.application.canvasPosition.right - this.mouse.x : w;
		};

		if(this.options.grid) {
			l -= l % this.options.grid;
			t -= t % this.options.grid;					
		};
		

		this.currentElement.css({ width: w, height: h, top: t, left:l });
	},
	startResizeBox: function(event, element){
		this.mode = 'resizeBox';
		for(var a = 0, b = this.compass.length; a < b; a++){
			var i = this.resizeHandle.hasClass(this.compass[a]);
			if(i){
				this.resizeDirection = this.compass[a];
				break;
			}
		};		
	},
	resizeBox: function(event, position, mouse){
		
		if(this.options.grid) {
			mouse.x -= mouse.x % this.options.grid;
			mouse.y -= mouse.y % this.options.grid;						
		};
		
		var margin = true;
		var relative = true;
		var _position = this.currentElement.position();

		var t = _position.top;
		var l = _position.left;

		var w = this.currentElement.width();
		var h = this.currentElement.height();

		var b = _position.top + h;
		var r = _position.left + w;
			

		
		if(this.resizeDirection == 'n' || this.resizeDirection == 'ne' || this.resizeDirection == 'nw'){
			t = Math.max(mouse.y - visualHUD.application.canvasPosition.top, 0);
			h = Math.max(b - t, 1); // _position.left - mouse.x - visualHUD.application.canvasPosition.left;
			if(h == 1){
				t = b - h;
			};
			
		};
		if(this.resizeDirection == 'w' || this.resizeDirection == 'nw' || this.resizeDirection == 'sw'){
			l = Math.max(mouse.x - visualHUD.application.canvasPosition.left, 0);
			w = Math.max(r - l, 1); //_position.top - mouse.y -  visualHUD.application.canvasPosition.top;
			
			if(w == 1){
				l = r - w;
			};

			
		};
		
		if(this.resizeDirection == 'e' || this.resizeDirection == 'ne' || this.resizeDirection == 'se'){
			w = mouse.x - _position.left - visualHUD.application.canvasPosition.left;
			w = mouse.x > visualHUD.application.canvasPosition.right ? visualHUD.application.canvasPosition.right - visualHUD.application.canvasPosition.left - _position.left : w;
		};
		if(this.resizeDirection == 's' || this.resizeDirection == 'se' || this.resizeDirection == 'sw'){
			h = mouse.y - _position.top -  visualHUD.application.canvasPosition.top;
			h = mouse.y > visualHUD.application.canvasPosition.bottom ? visualHUD.application.canvasPosition.bottom - visualHUD.application.canvasPosition.top - _position.top : h;
		};
		
		if(this.options.grid) {
			w -= w % this.options.grid;
			h -= h % this.options.grid;					
		};
		
		this.currentElement.css({ width: Math.max(w, 1), height:  Math.max(h, 1),top: t, left: l });
	},
	startMoveElement: function(event, element){
		this.currentElement.addClass('drag-start');
		this.slaveElements = [];
		this.offsets = [];
		this.drawLine = false;
		
		var masterElement;
		if(visualHUD.application.selectedItems.length > 1){
			for(var a = 0, b = visualHUD.application.selectedItems.length; a < b; a++){
				var isMatch = visualHUD.application.selectedItems[a].element.get(0) == this.currentElement.get(0);
				if(isMatch){
					masterElement = visualHUD.application.selectedItems[a].element;
				} else {
					this.slaveElements.push(visualHUD.application.selectedItems[a].element);
				};
			};
			var masterPosition = masterElement.position();

			for(a = 0, b = this.slaveElements.length; a < b; a++){
				var slavePosition = this.slaveElements[a].position();

				this.offsets.push({
					top: masterPosition.top - slavePosition.top,
					left: masterPosition.left - slavePosition.left
				});
			};
		};		
		
		this.mode = 'moveElement';
	},			
	moveElement: function(event, position, mouse){
		var newPosition = visualHUD.application.checkPosition(this.currentElement, position);
		this.currentElement.css(newPosition);	
		
		for(a = 0, b = this.slaveElements.length; a < b; a++){
			this.slaveElements[a].css({
				top: newPosition.top - this.offsets[a].top,
				left: newPosition.left - this.offsets[a].left
			});
		};
	}	
};

visualHUD.application = {
	selectedItem: null,
	selectedItems: [],
	deletedItems: [],
	styleButtons: $(''),
	canvasAction: 'default',
	started: false,
	saved: false,
	isDraft: false,
	init: function(options){
		$.extend(this, options || {});
		this.canvas = $('#hudCanvas');
		this.hudElementsWrap = this.canvas.find('div.hud-elements').empty();
		this.setupCanvas();
		
		this.stageControls = $('#stageControls');
		this.setupStageControls();
		
		this.canvasToolbar = $('#canvasToolbar');
		this.canvasExtras = this.canvas.find('div.canvas-extras');
		this.setupCanvasToolbar();
		
		this.settingsArea = $('#settingsArea');
		
		this.stageControls = $('#stageControls');
		
		this.groupActionsPanel = $('#groupActionsPanel');
		this.setupGroupActions();
		
		this.trashCan = $('<div class="hidden" />').appendTo(document.body);

		xpk.Hint(this.settingsArea,{
			delay: 200,
			width: 250,
			fromSelector: 'li',
			source: function(element){
				if(element[0].className.indexOf('item-status') == -1) {
					return element.find('span.item-name').html();
				} else {
					return false;
				};
			}
		});

		this.bound = {
			selectItem: $.proxy(this.selectItem, this),
			resize: $.proxy(this.positionLayout, this),
			recalcCanvas: $.proxy(this.getCanvasPosition, this)
		};
		
		var draft = this.isDraft = window.localStorage.vhudDraft;
		window.$window = $(window);
		
		$window.unload(function(){
			if(visualHUD.application.started && !visualHUD.application.saved){
				window.localStorage.vhudDraft = visualHUD.application.serialize(true);
			}
		});
		
		$window.resize(this.bound.resize);
		this.positionLayout();
		
		$('#downloadButton').click(function(){
			window.localStorage.vhudDraft = null;
			delete window.localStorage.vhudDraft;
			visualHUD.application.started = false;
			visualHUD.application.saved = true;
		});
		
		$window.load(function(){
			if(draft){
				visualHUD.application.started = true;
				visualHUD.loadPreset(JSON.parse(draft), function(){
					document.getElementById('preloader').style.display = 'none';
				});
				window.localStorage.vhudDraft = null;
				delete window.localStorage.vhudDraft;
			} else {
				document.getElementById('preloader').style.display = 'none';
			};
		});

	},
	setupStageControls: function(){
		var _this = this;
		
		var library = visualHUD.constructor.buttons;
		var libItemsList = this.stageControls.find('ul.library-items:first').empty();

		var createButton = function(k){
			var _data = library[k];
			_data.name = k;
			var $li = $('<li />').addClass(_data.cssClass).data('elementConstructorData', _data);
			var html = ('<span class="item-name">%text</span>').replace(/%text/g, _data.label);
			$li.html(html);
			
			return $li;
		};
		
		for(var key in library){
			createButton(key).appendTo(libItemsList);
		};

		var presetBlock = $('#presetManager');
		
		var loadPreset = function(presetName){
			if(presetName){
				_this.clearHUD();
				_this.isDraft = true;				
				visualHUD.loadPreset(visualHUD.presets[presetName].preset);
			};
			return false;
		};

		visualHUD.setupToolbar(presetBlock);		
		var presetBlock = presetBlock.find('li.load ul');

		var selectOptions = [];
		for(key in visualHUD.presets){
			selectOptions.push(('<li><a href="#" class="{0}">{1}</a></li>').format(key, visualHUD.presets[key].name));
		};
		presetBlock.append(selectOptions.join(''));
		
		presetBlock.delegate('a', 'click', function(){
			return loadPreset(this.className);
		});
		
		var dropArea = this.getCanvasPosition();
		var hudCanvas = this.canvas;
		
		var dragCreate = new xpk.DragBase({
			ticks: 2,
			tolerance: 3,
			position: 'offset',
			bodyDragClass: 'new-item-drag',
			onbeforestart: function(){
				dropArea = _this.canvasPosition;
			},
			onstart: function(){
				var css = {
					left: this.mouse.x + this.moveOffset.x,
					top: this.y + this.moveOffset.y,
					display: 'block'
				};
				
				this.ghost.addClass(this.currentElement[0].className).css(css);
				this.currentElement.addClass('drag-start');
			},
			ondrag: function(event, position, mouse){
				this.ghost.css(position);
		
				if(dropArea.top < mouse.y && dropArea.left < mouse.x && dropArea.right > mouse.x && dropArea.bottom > mouse.y){
					if(!hudCanvas.hasClass('new-item-drop-over')){
						hudCanvas.addClass('new-item-drop-over')
					};
				} else {
					if(hudCanvas.hasClass('new-item-drop-over')){
						hudCanvas.removeClass('new-item-drop-over')
					};
				};
			},
			ondragover: function(event){
			},
			ondragout: function(event){
			},
			ondrop: function(event, _target){	
				this.ghost.removeClass(this.currentElement[0].className);
				this.currentElement.removeClass('drag-start');
				hudCanvas.removeClass('new-item-drop-over');
				var mouse = this.getMouse(event);
				var hit = dropArea.top < mouse.y && dropArea.left < mouse.x && dropArea.right > mouse.x && dropArea.bottom > mouse.y;
				if(hit){
					injectNewElement(this.currentElement, mouse);
				};
			}
		});
		
		libItemsList.delegate('li', 'mousedown', function(event){
			var $target = $(this);			
			dragCreate.start(event, $target);
			if (event.stopPropagation) event.stopPropagation();
			if (event.preventDefault) event.preventDefault();
			return false;
		});

		libItemsList.delegate('li', 'dblclick', function(event){
			var $target = $(this);			
			
			var $window = $(window);
			var canvasPosition = _this.canvas.offset();
			var canvasSize = {width: _this.canvas.width(), height: _this.canvas.height()};
			
		
			injectNewElement($target, {x: canvasPosition.left + canvasSize.width/2, y:  canvasPosition.top + canvasSize.height/2 })
			
			if (event.stopPropagation) event.stopPropagation();
			if (event.preventDefault) event.preventDefault();
			return false;
		});
		
		var injectNewElement = function(_el, _pos){
			var _dropData = _el.data('elementConstructorData');
			var newItem = _dropData.fn.apply(visualHUD.constructor.fn, [_dropData, _pos]);
			
			_this.started = true;
			_this.selectItem(false);
			_this.selectItem(newItem);
			drawTools.children().removeClass('active');
			_this.canvasAction = 'default';			
			_this.getItemStatus(newItem);
		};
		
		var drawTools = this.drawTools = $('#drawControls').delegate('li', 'click', function(event){

			drawTools.children().not(this).removeClass('active');
			var $target = $(this);
			
			if($target.hasClass('disabled')) return;
			
			$target.toggleClass('active');
			
			var active = this.className.indexOf('active') >= 0;
			_this.canvasAction = active ? this.id : 'default';
			
			if (event.stopPropagation) event.stopPropagation();
			if (event.preventDefault) event.preventDefault();
			return false;
		});

	},
	setupGroupActions: function(){
		var alignItemsList = $('#alignControls');
		var arrangeItemsList = $('#arrangeControls');
		
		var deleteButton = this.groupActionsPanel.find('button.delete-items');
		
		deleteButton.click($.proxy(this, 'deleteElement'));
		
		alignItemsList.delegate('li', 'click', function(event){
			var $target = $(this);
			var _alignPosition = $target.attr('class').split('-')[1];
			visualHUD.application.alignEdges(_alignPosition);
			
			if (event.stopPropagation) event.stopPropagation();
			if (event.preventDefault) event.preventDefault();
			return false;
		});	

		arrangeItemsList.delegate('li', 'click', function(event){
			var $target = $(this);
			var _alignPosition = $target.attr('class');
			visualHUD.application.arrangeLayers(_alignPosition);
			
			if (event.stopPropagation) event.stopPropagation();
			if (event.preventDefault) event.preventDefault();
			return false;
		});	
		
	},
	arrangeLayers: function(_className){
		if(this.selectedItems.length != 1)
			return;

		var targetElement = this.selectedItems[0].element;		
		var elementType = this.selectedItems[0].data.properties.itemType;
		if( elementType != 'rect')
			return;
		
		var hudElementsWrap = this.hudElementsWrap;
		
		var actions = {
			'bring-front': function(){
				return {
					element: hudElementsWrap,
					fn: 'appendTo'
				};
			},
			'send-back': function(){
				return {
					element: hudElementsWrap,
					fn: 'prependTo'
				}
			},
			'bring-forward': function(){
				return {
					element: targetElement.next(),
					fn: 'insertAfter'
				}
			},
			'send-backward': function(){
				return {
					element: targetElement.prev(),
					fn: 'insertBefore'
				}
			}
		};
		
		var _direction;
		var fnData;
		
		var hudItems = this.hudElementsWrap.find('div.hud-item');
		
		for(var k in actions){
			if(_className.indexOf(k) > -1){
				fnData = actions[k]();
				break;
			};
		}
		
		if(fnData.element.length && fnData.element[0] != targetElement[0]){
			targetElement[fnData.fn](fnData.element)
		};
		
	},
	alignEdges: function(_alignPosition){

		var getElementBox = function(el){
			var position = el.position();
			var size = {
				width: el.width(),
				height: el.height()
			}
			
			return $.extend(position, size);
		};
		
		var alignItem = function(element, box){
			switch(_alignPosition){
				case 'top':
					element.css('top', boxes[0].top);
					break;
				case 'bottom':
					element.css('top', boxes[0].top + boxes[0].height - box.height);
					break;
				case 'vertical':
					element.css('top', boxes[0].top + (boxes[0].height - box.height)/2);
					break;
				case 'left':
					element.css('left', boxes[0].left);
					break;
				case 'right':
					element.css('left', boxes[0].left + boxes[0].width - box.width);
					break;
				case 'horizontal':
					element.css('left', boxes[0].left + (boxes[0].width - box.width)/2);
					break;
			};
		};
		
		var boxes = [];
		if(this.selectedItems.length == 1){
			boxes.push({
				top: 0,
				left: 0,
				width: this.canvasPosition.width,
				height: this.canvasPosition.height
			});
			alignItem.apply(this, [this.selectedItems[0].element, getElementBox(this.selectedItems[0].element)]);
		} else {
			for(var a = 0, b = this.selectedItems.length; a < b; a++){
				boxes.push(getElementBox(this.selectedItems[a].element));
				if(a > 0){
					alignItem.apply(this, [this.selectedItems[a].element, boxes[a]])
				};
			};
		};
	},
	getCanvasPosition: function(){
		var offset = this.canvas.offset();
		var size = {
			width: this.canvas.width(),
			height: this.canvas.height()
		};
		this.canvasPosition = {
			top: offset.top,
			left: offset.left,
			right: offset.left + size.width,
			bottom: offset.top + size.height,
		};
		
		$.extend(this.canvasPosition, size);
		return this.canvasPosition;
	},
	setupCanvasToolbar: function(){

		var LI = this.canvasToolbar.children();
		visualHUD.setupToolbar(this.canvasToolbar);
		
		var _this = this;

		var toolbarHint = xpk.Hint(this.canvasToolbar,{
			delay: 50,
			width: 200,
			fromSelector: 'li.root-item:not(.active)'
		});	
		
		var extrasClasses = {
			'lagometr': 'draw-lag',
			'speedometr': 'draw-speed',
			'pickup': 'draw-pickup',
			'drawGrid': {
				'0': 'no-grid',
				'5': 'grid-5',
				'10': 'grid-10'
			},
			'drawGun': {
				'0': 'no-gun',
				'1': 'gun-1'
			},
			'drawWeaponbar': {
				'0': 'no-gun',
				'1': 'wbar-1',
				'2': 'wbar-2',
				'3': 'wbar-3',
				'4': 'wbar-4'
			},
			'drawTeamoverlay': {
				'0': 'no-teamoverlay',
				'1': 'teamoverlay-1',
				'2': 'teamoverlay-2'
			}
		}
		
		var setupMenu = function(_item){
			_item.click(function(event){
				toolbarHint.hide();
			});
		};

		var setupSubMenu = function(_item){
			_item.delegate('input[type=radio]', 'click', function(event){
				var value = this.value;
				var name = this.name;
				var valueElement = _item.closest('li').find('strong.item-value').text(value);
				
				if(name == 'snapGrid'){
					_this.drag.setOptions({grid: value * 1});
					return;
				};

				if(name == 'canvasShot'){
					_this.canvas.parent().attr('class', 'main-panel canvas-' + value);
					return;
				};
				
				var extra = extrasClasses[name];
				var canvasExtras = visualHUD.application.canvas;
				var fn = 'removeClass';
				
				for(var x in extra){
					fn = value == x ? 'addClass': 'removeClass';
					canvasExtras[fn](extra[x])
				};
			});

			_item.delegate('input[type=checkbox]', 'click', function(event){
				var value = this.value;
				var name = this.name;
				var valueElement = _item.closest('li').find('strong.item-value').text(value);
				
				
				var extra = extrasClasses[name];
				var canvasExtras = visualHUD.application.canvas;
				var fn = this.checked ? 'addClass': 'removeClass';
				canvasExtras[fn](extra);
			});
			
		};
		
		
		LI.each(function(){
			var $this = $(this);
			var submenu = $this.find('ul');
			
			setupMenu($this);
			setupSubMenu(submenu);
		});
		
		this.canvasToolbar.find('input:checked').trigger('click');
		
	},
	checkPosition: function(element, position){

		var canvasElement = this.canvas;
		var limits = this.canvasPosition;;
		
		var elementSize = {
			width: element.width(),
			height: element.height()
		};
	
		if(position.left + elementSize.width > canvasElement.width()){
			position.left = canvasElement.width() - elementSize.width;
		};

		if(position.top + elementSize.height > canvasElement.height()){
			position.top = canvasElement.height() - elementSize.height;
		};
		
		position.left = position.left < 0 ? 0 : position.left;
		position.top = position.top < 0 ? 0 : position.top;
		
		return position;
	},
	setupCanvas: function(){
		var _this = this;
		var bPreventBodyAction = false;
		
		this.drag = new xpk.DragBase({
			ticks: 0,
			tolerance: 2,
			grid: 0,
			init: function(){
				this.compass = ['nw', 'n', 'ne','e','se','s', 'sw', 'w'];
				var handles = [];
				for(var a = 0, b = this.compass.length; a < b; a++){
					handles.push('<div class="resize-handle '+ this.compass[a] +'"></div>');
				};
				this.drawBox = $('<div class="hud-item"><div class="hud-item-box"></div>'+ handles.join('') +'</div>').width(1).height(1);

			},
			onbeforestart: function(event, _mouse){
				this.offsets = [];
			},
			onstart: function(event, _mouse){
				var mode = this.mode;
				this[mode]();
				console.log(this.mouse.x - _mouse.x)
				console.log(this.mouse.y - _mouse.y)
			},
			ondrag: function(event, position, mouse){
				var mode = this.mode;
				this[mode](event, position, mouse);
			},	
			ondragover: function(event){
			},
			ondragout: function(event){
			},
			ondrop: function(_target){
				switch(this.mode){
					case 'moveElement':
						this.currentElement.removeClass('drag-start');
						
						break;
					case 'drawRect':
						var dataObject = {
							'name': 'rectangleBox',
							'itemType': 'rect',
							'label': 'Rectangle box',
							'cssClass': 'lib-element-rect',
						};
						visualHUD.constructor.fn.createRect(dataObject, this.currentElement);
						this.currentElement.trigger('click');
						break;
					case 'resizeBox':
						var _data = this.currentElement.data('HUDItem');
						var size = {
							width: this.currentElement.width(),
							height: this.currentElement.height()
						};						
						
						visualHUD.setupHudItem[_data.properties.itemType](this.currentElement, _data, size);
						
						for(var k in size){
							var element = _data.form.get(0)[k];
							if(element) element.value = size[k];
							
							if(element.className.indexOf('range') != -1){					
								$(element).trigger('blur');
							};							
						};
						
						break;
						
				};
		
				_this.getItemStatus(this.currentElement);
				
				window.setTimeout(function(){
					bPreventBodyAction = false;
				}, 50);
			}
		});
		
		$.extend(this.drag, visualHUD.dragInterface);
		
		this.hudElementsWrap.mousedown(function(event){
			var $target = $(event.target);
			
			var resizeHandle = $target.closest('div.resize-handle', this);
			var hudItem = $target.closest('div.hud-item', this);
			
			if(resizeHandle.length && _this.canvasAction == 'default'){
				_this.drag.setDragHandle(resizeHandle).setOptions({bodyDragClass: 'resize'}).setMode('startResizeBox').start(event, hudItem);
				return false;
			};
			
			
			if(hudItem.length && _this.canvasAction == 'default'){
				_this.drag.setOptions({bodyDragClass: 'drag'}).setMode('startMoveElement').start(event, hudItem);
				return false;
			};
			
			if(_this.canvasAction == 'drawRect'){
				_this.drag.setOptions({bodyDragClass: 'draw'}).setMode('startDrawRect').start(event);
				bPreventBodyAction = true;
				return false;
			};

		});
		
		this.hudElementsWrap.delegate('div.hud-item', 'click', function(event){
			event.stopPropagation();
			var hudItem = $(this);
			_this.selectItem(hudItem, event.shiftKey, _this.drag.offsets.length);
		});
		
		$(document).bind('keydown', $.proxy(this, 'keyboardListiner'));
		
	},
	selectItem: function(_item, _multiple, _drag){
		var _this = this;
		
		var deselectAll = function(){
			this.stageControls.removeClass('hidden');
			this.groupActionsPanel.addClass('hidden');
			for(var a = 0, b = this.selectedItems.length; a < b; a++){
				this.selectedItems[a].data.form.addClass('hidden').data('focusedElement', null);
				this.selectedItems[a].element.removeClass('selected');
			};
			this.selectedItems = [];
			this.drag.offsets = [];

			this.drawTools.children().removeClass('active');
			this.canvasAction = 'default';
			$('body').unbind('click', this.bound.selectItem);
		};
		
		if(_drag) return;
		
		var isSelected = _item ? this.checkIfSelected(_item[0]) : -1;
		if(isSelected  > -1){
			var selectedItem = this.selectedItems[isSelected];
//			this.getItemStatus(selectedItem.element, selectedItem.data);
			var focusedElement = selectedItem.data.form.data('focusedElement');
			if(focusedElement) focusedElement.blur();
			return;
		};
		
		if(!_item || !_multiple){
		   	deselectAll.call(this);
		};
		
		if(_item && _item.length){

			var selectedItem = {
				element: _item.addClass('selected'),
				data: _item.data('HUDItem')
			};
			
			window.setTimeout(function(){
				$('body').bind('click', _this.bound.selectItem);
			}, 10);
		
			this.selectedItems.push(selectedItem);			
			this.stageControls.addClass('hidden');
			
			if(this.selectedItems.length == 1){
				var focusedElement = selectedItem.data.form.data('focusedElement');
				if(focusedElement) focusedElement.blur();
		
				this.groupActionsPanel.addClass('hidden');
//				this.selectedItems[0].data.form.removeClass('hidden');
				
				window.setTimeout(function(){
					selectedItem.data.form.removeClass('hidden');
				}, 50);
			
			} else {
				for(var a = 0, b = this.selectedItems.length; a < b; a++){
					this.selectedItems[a].data.form.addClass('hidden');
				};
				this.groupActionsPanel.removeClass('hidden');
			};
		};
	},
	getItemStatus: function(_element, _data){
		
		if(!_element){
			console.log('No element');
			return;
		};
		
		if(!_data){
			var _data = _element.data('HUDItem');
		};

		var propsList = {
			'top': 'X',
			'left': 'Y',
			'width': 'W',
			'height': 'H'
		};
		
		var form = _data.form;
		var _oldCoordinates = _data.properties.coordinates || {};
		var coordinates = _element.coordinates(true, false);
		var isUpdated = this.isDraft;

		for(var k in coordinates){
			if(coordinates[k] != _oldCoordinates[k]){
				isUpdated = true;
				break;
			};
		}
		var placeholder = _data.formStatusBar;

		if(!placeholder){
			var toolbar = _data.form.find('ul.app-toolbar');
			placeholder = $('<li class="item-status"></li>').prependTo(toolbar);
			_data.formStatusBar = placeholder;
		};
		
		var html = [];
		
		if(isUpdated){
			window.setTimeout(function(){
				_data.properties.coordinates = coordinates;
				for(var k in propsList){
					html.push('<span class="mr-10"><span class="item-name">'+ propsList[k] +':</span><strong class="item-value">'+ coordinates[k] +'</strong></span>');
				};
				html = html.join('');								   
				placeholder.html(html);
			}, 50);
		};
		
	},
	checkIfSelected: function(_el){
		for(var a = 0, b = this.selectedItems.length; a < b; a++){
			if(this.selectedItems[a].element[0] == _el) {
				return a;
			} else {
				return -1;
			};
		};
	},
	keyboardListiner: function(event){
		
		var nodeName = event.target.nodeName;
		
		if(this.selectedItems.length == 0 || nodeName.match(/input|select|textarea/gi)){
			return;
		}
		
		var moveMap = {
			'37': 'left',
			'38': 'top',
			'39': 'left',
			'40': 'top'
		};
		var arrangeMap = {
			'38': ['bring-front', 'bring-forward'],
			'40': ['send-back', 'send-backward']
		};		
		
		// keyCode: 38 top
		// keyCode: 39 right
		// keyCode: 40 bottom
		// keyCode: 37 left
		// shiftKey
		
		console.log(event.keyCode)

		if(event.keyCode == 46) {
			return this.deleteElement();
		};
		
		if(event.keyCode == 82){
			$('#drawRect').trigger('click');
			return;
		};
		
		var moveKey = moveMap[event.keyCode];
		var arrangeKey = arrangeMap[event.keyCode];
		
		
		
		if(moveKey && !event.ctrlKey) {
			var delta = event.shiftKey ? 10 : 1;
			
			if(event.keyCode == '37' || event.keyCode == '38'){
				delta = -1 * delta;
			};
			
			for(var a = 0, b = this.selectedItems.length; a < b; a++){
				var element = this.selectedItems[a].element
				var currentPosition = element.position();
				currentPosition[moveKey] += delta;
				var newPosition = this.checkPosition(element, currentPosition);
				element.css(newPosition);
			};
			
			if(this.selectedItems.length == 1){
				var selectedItem = this.selectedItems[0];
				this.getItemStatus(selectedItem.element, selectedItem.data);
			};
			
			return false;
		};
		
		if(arrangeKey && event.ctrlKey){
			var actionIndex = event.shiftKey ? 0 : 1;
			this.arrangeLayers(arrangeKey[actionIndex]);
			return false;
		};
		

	},
	deleteElement:function(_silent){
		if(this.selectedItems.length){
			var result = _silent || window.confirm('Are you sure you want to delete selected item(s)?');
			if(!result) return false;
		} else {
			return true;
		};
		
		for(var a = 0; a < this.selectedItems.length ; a++){
			var element = this.selectedItems[a].element;
			var form = this.selectedItems[a].data.form;
			
			element.removeClass('selected').appendTo(this.trashCan);
			form.addClass('hidden');
			
			this.deletedItems.push(this.selectedItems[a]);
		};
		
		this.selectedItems = [];
		this.selectItem();
		return false;
	},
	copyProperties: function(element){
		var _data = element.data('HUDItem');
		var props = _data.properties;

		var propsToRemove = ['cssClass','label','name', 'text'];
		
		this.styleButtons.attr('disabled', false);
		this.elementPropsClipboard = $.extend({}, props);

		var ranges = visualHUD.constructor.colorRangeValues;

		
		for(var k in ranges){
			propsToRemove.push('colorRange_' + k);
		};
		for(var a in propsToRemove){
			delete this.elementPropsClipboard[propsToRemove[a]];			
		};
			
		return false;
	},
	applyProperties: function(element){
		var _data = element.data('HUDItem');
		var props = _data.properties;
		var form = _data.form;
		
		var clipboardData = this.elementPropsClipboard;
		
		if(clipboardData){
			var matchedElements = clipboardData.itemType == props.itemType;
			if(matchedElements){
				visualHUD.setupHudItem[clipboardData.itemType](element, _data, clipboardData);
			} else {
				clipboardData = {};
			};
		};
		
		for(var p in clipboardData){
			var formElement = form[0][p];
			if(formElement){
				var $el = $(formElement)
				if(formElement.type == 'checkbox'){
					formElement.checked = clipboardData[p];
				} else if(formElement.options){
					for(var a=0, b = formElement.options.length; a < b; a++){

						if(formElement.options[a].value == clipboardData[p]){
							formElement.selectedIndex = a;
						};
					};
					
				} else {
					formElement.value = clipboardData[p];
					//formElement.blur();
					if(formElement.className.indexOf('range') != -1){					
						$el.trigger('blur');
					};
				};
			};
		};
		
		this.styleButtons.attr('disabled', true);
												 
		this.elementPropsClipboard = null;
		return false;
	},
	positionLayout: function(){
		var appWrapper = $('#appWrapper');
		var appHeight = appWrapper.height();
		var docHeight = $(window).height();
		var margin = 10;
		if(appHeight < docHeight){
			margin = docHeight/2 - appHeight/2
		};
		appWrapper.css('top', margin)
		
		window.setTimeout(this.bound.recalcCanvas, 50);
	},
	serialize: function(json){
		this.selectItem();
		
		var items = this.hudElementsWrap.find('div.hud-item');
		
		var outputData = [];
		items.each(function(){
			var _element = $(this);
			var _data = _element.data('HUDItem');
			var _properties = $.extend({}, _data.properties);

			_properties.coordinates = _data.properties.coordinates || _element.coordinates(1,1);
			
			if(_data.properties.itemType == 'general'){
				_properties.iconCoordinates = _data.DOM.iconBlock.eq(0).coordinates(1,1);
				_properties.textCoordinates = _data.DOM.textBlock.eq(0).coordinates(1,1);
			};
			
			outputData.push(_properties);
		});
		

		return json ? JSON.stringify(outputData) : outputData;
	},
	clearHUD: function(){
		var _this = this;
		this.selectItem();
		
		var items = this.hudElementsWrap.find('div.hud-item');
		var forms = this.settingsArea.find('form.hud-item');
		
		items.remove();
		forms.remove();
	}
};

visualHUD.loadPreset = function(presetData, callback){
	var buttons = visualHUD.constructor.buttons;
	for(var a = 0, b = presetData.length; a < b; a++){
		var fn = buttons[presetData[a].name].fn;
		fn.apply(visualHUD.constructor.fn, [presetData[a]])
	};
	if(callback) callback();
};

visualHUD.reportError = function(_reportData){
	xpk.General.openModalWindow({
		element: true,
		id: 'errorReportFormWindow',
		width: 750,
		html: null,
		title: 'Send error report',
		cancel: function(){
			this.content.find('form').get(0).reset();
			this.content.find('button[type=submit]').attr('disabled', false);
			this.hide();
		}
	});

	$('#errorReportForm').submit(function(event){
		
		
		var serial = $(this).serializeArray();
		var text;
		
		var submitButton = $(this).find('button[type=submit]').attr('disabled', true);
		
		$.each(serial, function(){
			if(this.name == 'comments'){				
				this.value += '\n---------------\n\n';
				
				var map = ['Error', 'URL', 'Line'];
				for(var a=0, b = _reportData.length; a<b; a++){
					this.value += map[a] + ': ' + _reportData[a] + "\n";
				};				
			}
		});

		$.ajax({
			type: 'POST',
			url: this.action,
			data: serial,
			success: function(){
				xpk.Messages.success({
					title: 'Horray ;)',
					message: 'Thanks, mate. Your report has been sent'
				});	
				xpk.Windows.errorReportFormWindow.cancel();
				submitButton.attr('disabled', false);
			}
		});

		return false;
	});
};

window.onerror = function(errorMsg, url, lineNumber){

	var HTMLTemplate = '<p>There was an error on this page.</p><ul class="error-details mb-10">{0}</ul><button type="submit" value="Send report" class="button-small" id="sendBugReport"><span>Send report</span></button>';
	var repHTML = '<li><span class="weak">{0}</span>{1}</li>';
	
	var map = ['Error', 'URL', 'Line'];
	var args = arguments;

	var report = [];
	
	for(var a=0, b = args.length; a<b; a++){
		report.push(repHTML.format(map[a], args[a]));
	};

	var html = 	HTMLTemplate.format(report.join(''));
	
	xpk.Messages.error({
		title: 'Opps ;(',
		message: html
	});

	$$('sendBugReport').click(function(){		
		visualHUD.reportError(args);
		xpk.Messages.messenger.hide();
		return false;
	});

	return false;
};